package com.moonypoony.superactionrpg;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;


public class myRenderer implements Renderer {

	private int[] maptextures = new int[1316];
	private int[] charactertextures = new int[8];
	private int[] enemytextures = new int[8];
	private int[] dpad = new int[1];
	private int[] bbutton = new int[1];
	private FloatBuffer texturebuffer;
	private FloatBuffer buttonbuffer;
	private FloatBuffer verticebuffer;
	private FloatBuffer[] textbuffer = new FloatBuffer[96];
	private int[][] map = new int[40][40];
	private int[][] collision = new int[40][40];
	int scrollx;
	int scrolly;
	int offsetx;
	int offsety;
	boolean bbut = false;
	boolean dpadpressed = false;
	boolean check = true;
	int orientation;
	int lastorientation;
	int dpadid;
	int bbuttonid;
	long movetime;
	long animationtime;
	long dt;
	boolean frame = false;
	enemy enemy1;
	
	private Context context;
		
	
	public myRenderer (Context context) {
		this.context = context;
	}
	
	public void pressDPad(int direction, int id) {
		if(dpadid==-1) {
			dpadid = id;
		}
		if(id==dpadid) {
			orientation = direction;
			dpadpressed = true;
		}
	}
	
	public void pressbbutton(int id)
	{
		if (bbuttonid==-1 || bbuttonid == id) {
			bbuttonid = id;
			bbut = true;
		}
	}
	
	public void releaseButton(int id) {
		if (id == dpadid) {
			dpadid=-1;
		}
		if (id == bbuttonid) {
			bbuttonid=-1;
		}
	}
	
	public void checkCollision() {
		dpadpressed = false;
		//Check orientation
		
		switch(lastorientation) {
		case 0:	//down
			//check for collision with terrain
			//check for collision with enemies
			if(offsety>=2) {
				offsety+=2;
				dpadpressed = true;
			}
			else if(offsety==0) {
				if(collision[scrolly+9][scrollx+8]==0) {
					if(enemy1.collision(scrolly+9,scrollx+8)) {
						offsety+=2;
						dpadpressed = true;
					}
				}
			} 
			break;
		case 1:	//left
			//check if moved slightly up/down
			if(offsetx<=-2) {
				offsetx-=2;
				dpadpressed = true;
			}
			else if(offsetx==0) {
				if(collision[scrolly+8][scrollx+7]==0) {
					if(enemy1.collision(scrollx+7,scrolly+8)) {
						offsetx-=2;
						dpadpressed = true;
					}
				}
			} 
			break;
		case 2: //up
			//check if moved slightly left/right
			if(offsety<=-2) {
				offsety-=2;
				dpadpressed = true;
			}
			else if(offsety==0) {
				if(collision[scrolly+7][scrollx+8]==0) {
					if(enemy1.collision(scrollx+8,scrolly+7)) {
						offsety-=2;
						dpadpressed = true;
					}
				}
			}
			break;
		case 3:	//right
			//check if moved slightly up/down
			if(offsetx>=2) {
				offsetx+=2;
				dpadpressed = true;
			}
			else if(offsetx==0) {
				if(collision[scrolly+8][scrollx+9]==0) {
					if(enemy1.collision(scrollx+9,scrolly+8)) {
						offsetx+=2;
						dpadpressed = true;
					}
				}
			}
			break;
		}

	}
	
	public void drawText(GL10 gl, String text, float posx, float posy ) {
		
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		//gl.glBindTexture(GL10.GL_TEXTURE_2D, fonttexture[0]);
		gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		char[] letters = text.toCharArray();
		int textureposition;
		
		for (int i=0; i<letters.length; i++) {
			textureposition = (int) letters[i]-32;			
			gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textbuffer[textureposition]);
			gl.glLoadIdentity();
			gl.glTranslatef(-1f+posx/240f, 1f-posy/400f, 0.0f);
			gl.glScalef(7f/240f, 15f/400f, 1.0f);
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
			posx+=8;
		}
		
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glDisable(GL10.GL_TEXTURE_2D);
	}
		
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		
		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
       
        loadMap("noob.map");
		loadTextures(gl);
		
		
		setBuffer();
		scrollx = 15;
		scrolly = 15;
		dpadid = -1;
		bbuttonid = -1;
		movetime = System.currentTimeMillis();
		animationtime = System.currentTimeMillis();
		lastorientation = 0;
		enemy1 = new enemy(1,1);
		enemy.map = new int[40][40];
		enemy.setRoute(collision, scrollx+8,  scrolly+8, 0, 0);
		enemy1.mapGenerated();

	}
	
		
	
	public void onDrawFrame(GL10 gl) {
		// Setup basic drawing things
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, verticebuffer);
        
        if(System.currentTimeMillis() - animationtime > 128) {
        	animationtime = System.currentTimeMillis();
        	
        	frame=!frame;
        }
        enemy1.updatePosition();
        if(dpadpressed || dpadid!=-1) {
        	if(offsetx==0 && offsety==0) {
        		lastorientation = orientation;
        	}
        	
        	dt = System.currentTimeMillis() - movetime;
        	if( dt> 16) {
        		movetime = System.currentTimeMillis();
        		checkCollision();
        		
        		if(check) {
        			enemy.setRoute(collision, scrollx+8,scrolly+8, offsetx, offsety);
        			enemy1.mapGenerated();
        			check = false;
				}
        		if(offsetx>=32) { offsetx=0; scrollx++; enemy.setRoute(collision, scrollx+8,scrolly+8, offsetx, offsety); enemy1.mapGenerated(); check = true; dpadpressed=false; }
        		if(offsetx<=-32) { offsetx=0; scrollx--; enemy.setRoute(collision, scrollx+8,scrolly+8, offsetx, offsety); enemy1.mapGenerated();check = true; dpadpressed=false;}
        		if(offsety>=32) { offsety=0; scrolly++; enemy.setRoute(collision, scrollx+8,scrolly+8, offsetx, offsety); enemy1.mapGenerated();check = true; dpadpressed=false;}
        		if(offsety<=-32) { offsety=0; scrolly--; enemy.setRoute(collision, scrollx+8,scrolly+8, offsetx, offsety); enemy1.mapGenerated();check = true;dpadpressed=false;}
        	}
        }
        
       
        
        for(int i=0; i<17; i++) {
        	for(int j=0; j<17; j++) {
        		if(scrollx+j<=39 && scrollx+j>=0 && scrolly+i<=39 && scrolly+i>=0)
        			drawSquare(gl, 128f+32f*j-offsetx, 32f*i-offsety, 32, 32, maptextures[map[scrolly+i][scrollx+j]]);
        	}
        }
        enemy1.draw(gl, texturebuffer, scrollx, scrolly, offsetx, offsety, enemytextures, (frame?1:0));

        gl.glLoadIdentity();
        gl.glTranslatef(-1.0f, -1.0f, 0.0f);
        gl.glScalef(0.4f,2f, 1.0f);
        gl.glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        
        gl.glLoadIdentity();
        gl.glTranslatef(0.6f, -1.0f, 0.0f);
        gl.glScalef(0.4f,2f, 1.0f);
        gl.glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        
        if(dpadpressed || dpadid!=-1) {
        	drawSquare(gl, 384f, 256f, 32f, 32f, charactertextures[lastorientation*2+(frame?1:0)] );
        } else {
        	drawSquare(gl, 384f, 256f, 32f, 32f, charactertextures[lastorientation*2]);
        }
        
        drawSquare(gl, 0f, 480f, 160f, 160f, dpad[0]);
        drawSquare(gl, 736f, 480f, 64f, 64f, bbutton[0]);
        
       
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		
	}
	
	public void drawSquare(GL10 gl, float posx, float posy, float w, float h, int texture) {
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texturebuffer);
		gl.glLoadIdentity();
		gl.glTranslatef(-1f+posx/400f, 1f-posy/240f, 0.0f);
		gl.glScalef(w/400f, h/240f, 1.0f);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
		

		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glDisable(GL10.GL_TEXTURE_2D);
		
	}
		
	public void onSurfaceChanged(GL10 gl, int w, int h) {
		gl.glViewport(0, 0, w, h);
		
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glFrustumf(-w/h, w/h, -1f, 1f, -1f, 1f);
		
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		
	}
	
	public void loadTextures(GL10 gl) {
		
		dpad[0] = getTexture(gl,"dpad.png");
		bbutton[0] = getTexture(gl, "bbutton.png");
		loadTileTextures(gl, "outdoor.png", maptextures, 1);
		loadTileTextures(gl, "characters.png", charactertextures, 1);
		loadTileTextures(gl, "enemies.png", enemytextures, 1);
	
	}
		
	public void setBuffer() {
		float[] vertexCoords = {
				0f, 0f,
				0f, 1f,
				1f, 0f,
				1f, 1f
		};
				
		float[] textureCoords = {
			0f, 1,
			0, 0f,
			1f, 1f,
			1f, 0f
		};
	
		float[] buttonCoords = {
			0f, 0.625f,
			0f, 0f,
			0.9375f, 0.625f,
			0.9375f, 0f
		};
	
		ByteBuffer byteBuf0 = ByteBuffer.allocateDirect(vertexCoords.length * 4);
		byteBuf0.order(ByteOrder.nativeOrder());
		verticebuffer = byteBuf0.asFloatBuffer();
		verticebuffer.put(vertexCoords);
		verticebuffer.position(0);
		
		
		ByteBuffer byteBuf1 = ByteBuffer.allocateDirect(textureCoords.length * 4);
		byteBuf1.order(ByteOrder.nativeOrder());
		texturebuffer = byteBuf1.asFloatBuffer();
		texturebuffer.put(textureCoords);
		texturebuffer.position(0);
		
		ByteBuffer byteBuf2 = ByteBuffer.allocateDirect(buttonCoords.length * 4);
		byteBuf2.order(ByteOrder.nativeOrder());
		buttonbuffer = byteBuf2.asFloatBuffer();
		buttonbuffer.put(buttonCoords);
		buttonbuffer.position(0);
		
		for (int i=0; i<6; i++) {
			for (int j=0; j<16; j++) {
				float[] textCoords = {
						0.0546875f*j, (i+1)*0.1171875f ,
						0.0546875f*j, i*0.1171875f,
						0.0546875f*(j+1), (i+1)*0.1171875f,
						0.0546875f*(j+1), i*0.1171875f
						
				};
				ByteBuffer byteBuf = ByteBuffer.allocateDirect(textCoords.length*4);
				byteBuf.order(ByteOrder.nativeOrder());
				textbuffer[i*16+j] = byteBuf.asFloatBuffer();
				textbuffer[i*16+j].put(textCoords);
				textbuffer[i*16+j].position(0);
			}
		}
		
	}
	
	public int getTexture(GL10 gl, String id) {

		int[] texture = new int[1];
        gl.glGenTextures(1, texture, 0); 
        gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); 
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 

        InputStream is = null;
        Bitmap bitmap = null; 
        try { 
        	 is = context.getAssets().open(id);
             bitmap = BitmapFactory.decodeStream(is); 
        } catch (IOException e) { }
        finally { 
                try { 
                        is.close(); 
                        is = null; 
                } catch (IOException e) { 
                } 
        } 

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 

        bitmap.recycle(); 
		return texture[0];
	
	}
	
	private void loadMap(String id) {
		
		InputStream is = null;
		int temp;
		
		try{
			is = context.getAssets().open(id);
			for(int i=0; i<40; i++) {
				for(int j=0; j<40; j++) {
					temp = is.read()*256;
					map[i][j] = is.read()+temp-1;
					temp = is.read()*256;
					collision[i][j] = is.read()+temp;
				}
			}
		} catch (IOException e) { }
		finally {
			try{
				is.close();
				is = null;
				
			} catch (IOException e) {
				
			}
		}
		
		
		
	}
	
	private void loadTileTextures(GL10 gl, String id, int[] texturearray, int offset) {

        InputStream is = null;
        Bitmap bitmap = null; 
        try { 
        	 is = context.getAssets().open(id);
             bitmap = BitmapFactory.decodeStream(is); 
        } catch (IOException e) { }
        finally { 
                try { 
                        is.close(); 
                        is = null; 
                } catch (IOException e) { 
                } 
        } 
        int bitmapwidth = bitmap.getWidth();
        int bitmapheight = bitmap.getHeight();
        gl.glGenTextures(texturearray.length, texturearray, 0);
        Bitmap tile = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
        
        int[] tilearray = new int[bitmapwidth*bitmapheight];
        bitmap.getPixels(tilearray, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
      
        for(int i=0; i<bitmapheight/(16+offset); i++) {
        	for(int j=0; j<bitmapwidth/(16+offset); j++) {
		        tile.setPixels(tilearray, offset*bitmapwidth+i*bitmapwidth*(16+offset)+offset+j*(16+offset) ,bitmapwidth, 0, 0, 16, 16);
		        gl.glBindTexture(GL10.GL_TEXTURE_2D, texturearray[i*(bitmapwidth/(16+offset))+j]); 
		        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
		        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST); 
		        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, tile, 0);
        	}
        }


        bitmap.recycle(); 
		tile.recycle();
	}
	
}
